import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:ulid/ulid.dart';

///
/// @Author: yangjie
/// @Date: 2020/11/24 7:06 PM
/// @Description:
///

typedef onScanResult = void Function(String?);

class PdaScanner {
  late MethodChannel _channel;
  onScanResult? callbackHandler;

  //id 如果一个页面有多个platformView,需要用id区分，此处没有使用
  PdaScanner._() {
    if (!kIsWeb) {
      if (Platform.isAndroid) {
        _channel =
            const MethodChannel("com.newcore.demo.flutter.plugin/pda/scanner");
        _channel.setMethodCallHandler(_onMethodCall);
      }
    }
  }

  ///<ulid, CallbackHandler>
  static final Map<String, _ScanCallbackHandler> _resultHandlers = {};

  static final List<String> _scanIdStack = [];

  Future<bool> _onMethodCall(MethodCall call) async {
    switch (call.method) {
      case 'onPDAScanResult':
        final String? result = call.arguments['result'];
        if (_scanIdStack.isNotEmpty) {
          //使用队尾回调函数（当前激活状态）
          var currentScanId = _scanIdStack.last;
          var handler = _resultHandlers[currentScanId];
          var state = handler?.context.findAncestorStateOfType();
          if (state?.mounted == true) {
            handler?.callback(result);
          }
        }
        return true;
    }
    throw MissingPluginException(
      '${call.method} was invoked but has no handler',
    );
  }

  Future<bool?> _disable() => _channel.invokeMethod<bool>('PDADisable');

  Future<bool?> _enable() => _channel.invokeMethod<bool>('PDAEnable');

  static final PdaScanner _instance = PdaScanner._();

  ///Return scanId
  static String startPDAScan(
      {required BuildContext context,
      required void Function(String?) onScanResult}) {
    if (kIsWeb) return '';
    if (Platform.isAndroid) {
      var scanId = Ulid().toCanonical();
      _resultHandlers[scanId] =
          _ScanCallbackHandler(context: context, callback: onScanResult);
      _instance._enable();
      _scanIdStack.add(scanId);
      return scanId;
    }
    return '';
  }

  static void stopPDAScan(String scanId) {
    if (kIsWeb) return;
    if (Platform.isAndroid && scanId.isNotEmpty == true) {
      _resultHandlers.remove(scanId);
      _scanIdStack.remove(scanId);
    }
  }

  static void enable() {
    if (kIsWeb) return;
    if (Platform.isAndroid) {
      _instance._enable();
    }
  }

  static void disable() {
    if (kIsWeb) return;
    if (Platform.isAndroid) {
      _instance._disable();
    }
  }
}

class _ScanCallbackHandler {
  _ScanCallbackHandler({required this.context, required this.callback});
  final BuildContext context;
  final void Function(String?) callback;
}
